/*
 * FontMetrics.java  0.4.0 / Oct 24, 2010
 *
 * Copyright (c) 2010 - 2011, cute4j.com and contributors.
 *
 * This software is licensed under the LGPL version 2.1 license.
 * A copy of this license is included in the file LICENSE-LGPL.txt.
 */
package com.cute4j.swing.graphics;

import com.cute4j.core.Disposable;
import com.cute4j.swing.Swing;

/**
 * Font Metrics.
 *
 * @cute4j.native
 *    generate="header"
 *
 * @author Slobodan Vrkacevic
 * @version 0.4.0
 */
public class FontMetrics implements Disposable {

// Static Initialization. ------------------------------------------------------

  static {
    Swing.initialize();
    _initialize();
  }

// Private Fields. -------------------------------------------------------------

  private final Object lock;
  private boolean disposed;
  private final Font font;
  private long _fontMetricsPointer;

// Package-Private Fields. -----------------------------------------------------

  int ascent;
  int descent;
  int height;
  int leading;

// Public Constructors. --------------------------------------------------------

  /**
   * Constructs new FontMetrics for the specified font.
   *
   * @param font the specified font
   *
   * @throws IllegalArgumentException if the font is <tt>null</tt>
   * @throws RuntimeException if native font metrics creation failed
   */
  public FontMetrics(Font font) {
    if (font == null) {
      throw new IllegalArgumentException("Null font");
    }
    lock = new Object();
    this.font = font;
    _fontMetricsPointer = font.acquireFontMetricsPointer();
    _getMetrics(_fontMetricsPointer); // NOPMD
  }

// Public Methods. -------------------------------------------------------------

  /**
   * Returns font.
   *
   * @return font
   */
  public Font getFont() {
    return font;
  }

  /**
   * Returns width of the specified string.
   *
   * @param str the string
   *
   * @return width of the specified string
   */
  public int stringWidth(String str) {
    synchronized (lock) {
      if (disposed) {
        _fontMetricsPointer = font.acquireFontMetricsPointer();
        disposed = false;
      }
      return _stringWidth(_fontMetricsPointer, str);
    }
  }

  /**
   * Returns font ascent.
   *
   * @return font ascent
   */
  public int getAscent() {
    return ascent;
  }

  /**
   * Returns font descent.
   *
   * @return font descent
   */
  public int getDescent() {
    return descent;
  }

  /**
   * Returns font height.
   *
   * @return font height
   */
  public int getHeight() {
    return height;
  }

  /**
   * Returns font leading.
   *
   * @return font leading
   */
  public int getLeading() {
    return leading;
  }

// Disposable Interface Implementation. ----------------------------------------

  /**
   * {@inheritDoc}
   */
  public final boolean isDisposed() {
    synchronized (lock) {
      return disposed;
    }
  }

  /**
   * {@inheritDoc}
   */
  public final void dispose() {
    synchronized (lock) {
      if (!disposed) {
        font.releaseFontMetricsPointer();
        disposed = true;
      }
    }
  }

// Overridden Methods. ---------------------------------------------------------

  /**
   * {@inheritDoc}
   */
  protected final void finalize() {
    dispose(); // NOPMD
  }

// Package-Private Native Methods. ---------------------------------------------

  native void _getMetrics(long fontMetricsPointer);

  native int _stringWidth(long fontMetricsPointer, String str);

// Package-Private Static Native Methods. --------------------------------------

  private static native void _initialize();

}
